﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using MQTTnet;
using MQTTnet.Client.Receiving;
using MQTTnet.Protocol;
using MQTTnet.Server;

namespace MQTT.Server
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        List<TopicItem> Topics = new List<TopicItem>();
        //  实战基于IOC容器  依赖注入  抽象-》实现
        private IMqttServer server;
        /// <summary>
        /// 逻辑代码以   Winform事件驱动   WPF数据驱动
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            // 理解设计模式
            server = new MqttFactory().CreateMqttServer();
            //。。。。。
            ///打开服务
            ///

            // 基本事件 
            server.StartedHandler = new MqttServerStartedHandlerDelegate(ServerStarted);
            server.StoppedHandler = new MqttServerStoppedHandlerDelegate(ServerStoped);

            // 客户端的连接与断开
            server.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(ClientConnected);
            server.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(ClientDisconnected);
            // 订阅/取消订阅
            server.ClientSubscribedTopicHandler = new MqttServerClientSubscribedHandlerDelegate(new Action<MqttServerClientSubscribedTopicEventArgs>(Server_ClientSubscribedTopic));
            server.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(new Action<MqttServerClientUnsubscribedTopicEventArgs>(Server_ClientUnsubscribedTopic));
            // 消息接收
            server.ApplicationMessageReceivedHandler =
               new MqttApplicationMessageReceivedHandlerDelegate(new Action<MqttApplicationMessageReceivedEventArgs>(Server_ApplicationMessageReceived));
        }

        /// <summary>
        ///  QoS   Quality of Service  服务质量
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btnStart_Click(object sender, RoutedEventArgs e)
        {
            if (server != null)
            {
                var optionBuilder = new MqttServerOptionsBuilder();
                // 绑定IP
                optionBuilder.WithDefaultEndpointBoundIPAddress(IPAddress.Parse(this.tbHostAddr.Text));
                // 绑定端口
                optionBuilder.WithDefaultEndpointPort(int.Parse(tbHostPort.Text));
                // 
                optionBuilder.WithDefaultCommunicationTimeout(TimeSpan.FromMilliseconds(5000));

                // 绑定用户名和密码
                optionBuilder.WithConnectionValidator(ConnectionValidate);

                //启用持久会话
                optionBuilder.WithPersistentSessions();//客户端需要将CleanSession设置为false

                //消息拦截器
                //optionBuilder.WithApplicationMessageInterceptor(ApplicationMessageInterceptor);

                IMqttServerOptions options = optionBuilder.Build();
                await server.StartAsync(options);
            }
        }

        private void ConnectionValidate(MqttConnectionValidatorContext context)
        {
            string un = "", pwd = "";
            this.Dispatcher.Invoke(() =>
            {
                un = this.tbUsername.Text;
                pwd = this.tbPassword.Text;
            });

            if (context.Username == un && context.Password == pwd)
            {
                // 验证通过
                context.ReasonCode = MqttConnectReasonCode.Success;
            }
            else
            {
                // 验证不通过
                context.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
            }
        }


        private void ServerStarted(EventArgs e)
        {
            this.txtRich.AppendText(">>> 服务已启动");
        }
        private void ServerStoped(EventArgs e)
        {
            this.txtRich.AppendText(">>> 服务已停止");
        }
        private void ClientConnected(MqttServerClientConnectedEventArgs e)
        {
            // 记录到客户端列表 
            this.Dispatcher.Invoke(() =>
            {
                lbClients.Items.Add(e.ClientId);
            });
            WriteLog(">>> 客户端" + e.ClientId + "连接");
        }
        private void ClientDisconnected(MqttServerClientDisconnectedEventArgs e)
        {
            // 记录到客户端列表 
            this.Dispatcher.Invoke(() =>
            {
                lbClients.Items.Remove(e.ClientId);
                WriteLog(">>> 客户端" + e.ClientId + "断开" + ">>>" + e.DisconnectType);
            });
        }
        private void Server_ClientSubscribedTopic(MqttServerClientSubscribedTopicEventArgs e)
        {
            var topic = Topics.FirstOrDefault(t => t.Topic == e.TopicFilter.Topic);
            if (topic == null)
            {
                topic = new TopicItem { Topic = e.TopicFilter.Topic, Count = 0 };
                Topics.Add(topic);
            }
            if (!topic.Clients.Exists(c => c == e.ClientId))
            {
                topic.Clients.Add(e.ClientId);
                topic.Count++;
            }

            this.Dispatcher.Invoke(() =>
            {
                this.lvTopic.Items.Clear();
                foreach (var item in this.Topics)
                {
                    this.lvTopic.Items.Add($"{item.Topic}:{item.Count}");
                }

            });
            WriteLog(">>> 客户端" + e.ClientId + "订阅主题" + e.TopicFilter.Topic);
        }

        private void Server_ClientUnsubscribedTopic(MqttServerClientUnsubscribedTopicEventArgs e)
        {
            var topic = Topics.FirstOrDefault(t => t.Topic == e.TopicFilter);
            if (topic != null)
            {
                topic.Count--;
                topic.Clients.Remove(e.ClientId);
            }

            this.Dispatcher.Invoke(() =>
            {
                this.lvTopic.Items.Clear();
                foreach (var item in this.Topics)
                {
                    this.lvTopic.Items.Add($"{item.Topic}:{item.Count}");
                }
            });
            WriteLog(">>> 客户端" + e.ClientId + "退订主题" + e.TopicFilter);
        }

        private void Server_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e)
        {
            WriteLog(">>> 收到消息" + e.ApplicationMessage.ConvertPayloadToString() + ",来自客户端" + e.ClientId + ",主题为" + e.ApplicationMessage.Topic);
        }

        private void ApplicationMessageInterceptor(MqttApplicationMessageInterceptorContext context) 
        {
            this.Dispatcher.Invoke(() =>
            {
                context.AcceptPublish = true;
            });
        }

        private void btnStop_Click(object sender, RoutedEventArgs e)
        {
            if (server != null)
            {
                server.StopAsync();
            }
        }

        public void WriteLog(string message)
        {
            if (!(txtRich.CheckAccess()))
            {
                this.Dispatcher.Invoke(() =>
                    WriteLog(message)
                    );
                return;
            }
            string strTime = "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] ";
            txtRich.AppendText(strTime + message + "\r");

        }
    }
    public class TopicItem
    {
        public string Topic { get; set; }
        public int Count { get; set; }
        public List<string> Clients { get; set; } = new List<string>();
    }
}
